<template>
  <el-dialog
    top="50px"
    width="800px"
    :title="title"
    append-to-body
    class="dialog-sm"
    :close-on-click-modal="false"
    :visible.sync="visible"
    :before-close="beforeClose"
  >
    <div class="border rounded">
      <div class="attach-upload-action">
        <div>已选{{ fileCount }}个文件，共{{ fileSizeLabel }}。</div>
        <div>
          <el-button size="small" class="btn-long" :disabled="loading" @click="handleSelectFile">
            选择文件
          </el-button>
          <el-button
            type="primary"
            size="small"
            class="btn-long"
            :loading="loading"
            @click="handleUploadFile"
          >
            开始上传
          </el-button>
        </div>
      </div>
      <div
        class="attach-upload-container"
        :class="{ 'is-dragover': dragover }"
        @drop.prevent="onDrop"
        @dragover.prevent="onDragover"
        @dragleave.prevent="dragover = false"
      >
        <div class="row">
          <div class="col-3" v-for="(file, index) in uploadFiles" :key="index">
            <div class="attach-upload-item" :class="{ disabled: loading }">
              <div class="aui-view">
                <img
                  v-if="file.viewType === 'image'"
                  :src="file.url"
                  :alt="file.name"
                  class="aui-view-img"
                />
                <i v-else class="fa aui-view-icon" :class="file.viewIcon"></i>
              </div>
              <div class="aui-action-mask"></div>
              <div class="aui-action">
                <div class="aui-action-btns">
                  <el-button
                    v-if="file.viewType === 'image'"
                    round
                    icon="el-icon-zoom-in"
                    @click="handlePreviewFile(index)"
                  ></el-button>
                  <el-button
                    v-else-if="file.viewType === 'link'"
                    round
                    @click="handleLinkFile(index)"
                  >
                    <i class="fa fa-external-link"></i>
                  </el-button>
                  <el-button
                    v-else
                    round
                    icon="el-icon-download"
                    @click="handleDownloadFile(index)"
                  ></el-button>
                  <el-button
                    round
                    icon="el-icon-delete"
                    @click="handleDeleteFile(index)"
                  ></el-button>
                </div>
              </div>
              <div v-if="file.loading" class="aui-percent-loading">
                <i class="el-icon-loading"></i>
              </div>
              <div class="aui-name">
                <div class="aui-name-bg"></div>
                <div class="aui-name-percent" :style="{ width: `${file.percent}%` }"></div>
                <div class="aui-name-text">{{ file.name }}</div>
              </div>
            </div>
          </div>

          <div class="col-3">
            <div class="attach-upload-item">
              <input
                type="file"
                ref="uploadInput"
                class="d-none"
                multiple
                :accept="mineTypes"
                @change="handleFileChange"
              />
              <el-button class="attach-upload-btn" :disabled="loading" @click="handleSelectFile">
                <i class="el-icon-upload attach-upload-btn-icon"></i>
                <div class="attach-upload-btn-text">点击上传</div>
                <div class="text-muted">或将文件拖到此处</div>
              </el-button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <small class="text-muted">{{ fileTypesLabel }}</small>
  </el-dialog>
</template>

<script>
import { downloadByLink } from '@vimi/utils-tool'
import { mineTypeMap } from '@/common/api/download'
import { uploadOss } from '@/common/api/oss'
import { formatFileSize } from '@/common/plugins/tools/format'
import { getFileType, revokeObjectURL } from '@/common/plugins/tools/file'
import { fileAdapter } from '@/bank/components/attach/index'

const noop = () => {}

export default {
  components: {},
  props: {
    visible: Boolean,
    title: {
      type: String,
      default: '添加附件',
    },
    attachId: {
      type: String,
      default: '',
    },
    attachTag: {
      type: String,
      required: true,
    },
    parentTag: {
      type: String,
      default: '',
    },
    fileTypes: {
      type: Array,
      default: () => [
        'png',
        'jpeg',
        'jpg',
        'bmp',
        'gif',
        'xls',
        'xlsx',
        'doc',
        'docx',
        'ppt',
        'pptx',
        'pdf',
        'txt',
        'mp3',
        'mp4',
        'mov',
        'wmv',
        'zip',
        'gzip',
        'rar',
      ],
    },
    beforeUpload: {
      type: Function,
      default: noop,
    },
  },
  data() {
    return {
      loading: false,
      uploadFiles: [],

      dragover: false,
    }
  },
  computed: {
    mineTypes() {
      return this.fileTypes.map(type => mineTypeMap.get(type) || type).join(',')
    },
    fileTypesLabel() {
      return '上传文件支持格式:' + this.fileTypes.join(';')
    },
    fileCount() {
      return this.uploadFiles.length
    },
    fileSize() {
      return this.uploadFiles.reduce((prev, curr) => {
        prev += curr.size
        return prev
      }, 0)
    },
    fileSizeLabel() {
      return formatFileSize(this.fileSize)
    },
  },
  watch: {},
  created() {},
  mounted() {},
  methods: {
    beforeClose() {
      this.reset()
      this.$emit('update:visible', false)
    },

    reset() {
      this.uploadFiles.forEach(file => {
        revokeObjectURL(file.url)
      })
      this.uploadFiles = []

      const { uploadInput } = this.$refs
      if (uploadInput) {
        uploadInput.value = ''
      }
    },

    handleSelectFile() {
      if (!this.attachId) {
        return this.$message.error('没有项目附件的相关信息，不能上传附件')
      }

      const { uploadInput } = this.$refs
      uploadInput.click()
    },

    handleFileChange(e) {
      const { files = [] } = e.target

      for (let i = 0; i < files.length; i++) {
        this.uploadFiles.push(fileAdapter(files[i]))
      }
      this.handleClear()
    },
    handleClear() {
      const { uploadInput } = this.$refs
      uploadInput.value = ''
    },

    handleDeleteFile(index) {
      const file = this.uploadFiles[index]
      revokeObjectURL(file.url)
      this.uploadFiles.splice(index, 1)
    },

    handleDownloadFile(index) {
      const { url, name } = this.uploadFiles[index]
      downloadByLink({ url, filename: name })
    },

    handleLinkFile(index) {
      const { url } = this.uploadFiles[index]
      window.open(url, '_blank')
    },

    handlePreviewFile(index) {
      const { url, name } = this.uploadFiles[index]
      this.$utils.viewer({
        images: [{ url, name }],
      })
    },

    // 上传OSS
    async handleUploadFile() {
      const { fileCount, uploadFiles } = this

      if (fileCount === 0) {
        return this.$message.error('请先选择文件')
      }

      // 上传前
      let bu = this.beforeUpload()
      if (bu && bu.then) {
        bu = await bu.then()
      }
      if (bu === false) {
        return
      }

      const promises = uploadFiles.map(it =>
        uploadOss({
          file: it.file,
          dir: `credit/attach/${this.attachId}`,
          type: 1,
          progress: ({ percent }) => {
            it.percent = percent
            it.loading = percent < 100
          },
        })
      )

      this.loading = true
      return Promise.all(promises)
        .then(list => {
          const attachData = list.map((url, index) => {
            const { viewType, name } = uploadFiles[index]
            return {
              attachment: url,
              parent_attachment_type: this.parentTag || '',
              attachment_type: this.attachTag,
              customer_related_id: this.attachId,
              file_type: viewType === 'image' ? 1 : 2,
              remark: name,
            }
          })
          return this.addData(attachData).then(res => ({ res, list }))
        })
        .then(res => {
          this.$emit('success', res)
          this.beforeClose()
        })
        .catch(err => {
          this.$message.error(err?.errorMessage ?? '上传失败')
        })
        .finally(() => {
          this.loading = false
        })
    },

    // 添加附件表
    async addData(data) {
      return this.$api.addBatch('credit', 'datum_customer_attachment', data)
    },

    // 拖拽上传
    onDragover() {
      if (!this.loading) {
        this.dragover = true
      }
    },

    // 拖拽放下
    onDrop(e) {
      if (this.loading) return
      this.dragover = false

      const { files } = e.dataTransfer
      for (let i = 0; i < files.length; i++) {
        const file = files[i]
        // 过滤类型
        if (this.fileTypes.includes(getFileType(file.name))) {
          this.uploadFiles.push(fileAdapter(file))
        }
      }
    },
  },
}
</script>

<style lang="scss" scoped>
.text-sm {
  font-size: 0.875rem;
}

.attach-upload-action {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid $border-color;
  padding: 0.5rem 1rem;
}

.attach-upload-container {
  width: 100%;
  height: 50vh;
  overflow-y: auto;
  padding-top: 0.5rem;
  padding: 0.5rem;
  padding-left: $grid-gutter-width;
  padding-right: $grid-gutter-width;
  transition: background-color 0.1s;

  @include scrollbar-theme();

  &.is-dragover {
    background-color: $primary-light-9;
    background-color: var(--primary-light-9);

    .attach-upload-item .el-button {
      background-color: $primary-light-9;
      background-color: var(--primary-light-9);
    }
  }
}

.attach-upload-item {
  position: relative;
  overflow: hidden;
  height: 136px;
  margin: 0.5rem 0;
  border: 1px solid $gray-200;
  border-radius: 0.25rem;

  &.disabled {
    cursor: not-allowed;
  }

  &:not(.disabled):hover {
    .aui-action {
      display: block;
    }
    .aui-action-mask {
      opacity: 1;
    }
  }
}

.aui-name {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 26px;

  &-text {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 100%;
    padding: 2px 0.5rem;
    color: #fff;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  &-bg {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.4);
  }

  &-percent {
    position: absolute;
    bottom: 0;
    left: 0;
    height: 100%;
    background-color: $primary;
  }
}

.aui-view {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;

  &-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  &-icon {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -68%);
    font-size: 3.6rem;
    color: $gray-600;
  }
}

.aui-action {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  height: 100%;
  transform: translate(-50%, -50%);
  display: none;

  &-btns {
    position: absolute;
    top: 50%;
    width: 100%;
    transform: translateY(-68%);
    display: flex;
    justify-content: center;
  }
}

.aui-action-mask {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.4);
  opacity: 0;
  transition: all 0.3s;
}

.aui-percent-loading {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.9);
  padding-top: 20%;
  text-align: center;
  color: $gray-500;
  font-size: 3rem;
}

.attach-upload-btn {
  width: 100%;
  height: 100%;
  border-radius: 0.1rem;
  border: none;
  color: $primary;
  color: var(--primary);

  &-icon {
    font-size: 4rem;
    color: $gray-500;
    margin-bottom: 0.5rem;
  }

  &:disabled {
    color: $gray-500;
    cursor: not-allowed;
  }
}
</style>
